﻿using NPOI.SS.UserModel;
using NPOI.XSSF.UserModel;
using Prism.Commands;
using Prism.Events;
using Prism.Regions;
using Prism.Services.Dialogs;
using SmartPlant.Core;
using SmartPlant.Core.Mvvm;
using SmartPlant.Model;
using SmartPlant.Model.DbContext.Biz;
using SmartPlant.Services;
using SmartPlant.Services.Interfaces;
using SmartPlant.WinCore;
using SmartPlant.WinCore.Config;
using SmartPlant.WinCore.Helper;
using System.Collections;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.IO;
using System.Windows;
using System.Windows.Input;
using Telerik.Windows.Controls;
using Telerik.Windows.Data;
using Unity;
using DialogParameters = Prism.Services.Dialogs.DialogParameters;

namespace SmartPlant.Modules.Base.ViewModels
{
    public class IndexTableViewModel : DynamicGridViewModelBase
    {
        private bool _localLoad = false;//是否从本地加载文件。 
        //private DelegateCommand<object> _localFileChangedCommand;
        //private DelegateCommand<object> _localFileSaveCommand;
        //private DelegateCommand<object> _localFileDelCommand;
        private DelegateCommand<object> _serverDataSaveCommand;
        private DelegateCommand<object> _columnSelectCommand;
        private DelegateCommand<object> _columnOrderChanged;
        private DelegateCommand<object> _saveCurView;
        private DelegateCommand<object> _SaveAsExcelCommand;

        private readonly IEventAggregator _eventAggregator;
        private ObservableCollection<FileDataInfo> _localFileList;
        private FileDataInfo _selectFile;
        /// <summary>
        /// 选中的pbs
        /// </summary>
        private List<ITreeNodeModel> _currentNodes = null;

        public IndexTableViewModel(
            IEventAggregator eventAggregator,
            IRegionManager regionManager,
            IUnityContainer unityContainer,
            IDynamicDataApi dynamicDataApi,
            IDialogService dialogService)
            : base(regionManager, unityContainer, dynamicDataApi, dialogService)
        {
            _eventAggregator = eventAggregator;
            _localFileList = new ObservableCollection<FileDataInfo>();

            _eventAggregator.GetEvent<PlanSelectedEvent>().Subscribe(OnPlanSelectedEvent);

            if (GlobalObject.CurrentNodes != null && GlobalObject.CurrentNodes.Count > 0)
            {
                OnPlanSelectedEvent(GlobalObject.CurrentNodes);
            }
        }

        private void OnPlanSelectedEvent(List<ITreeNodeModel> treeNodes)
        {
            if (_currentNodes == treeNodes) return;
            _currentNodes = treeNodes;

            _localLoad = false;
            IsBusy = true;
        }

        #region Prop
        ///// <summary>
        ///// 本地文件选择更改。
        ///// </summary>
        //public ICommand FileSelectChangedCommand
        //{
        //    get
        //    {
        //        if (_localFileChangedCommand != null) return _localFileChangedCommand;
        //        _localFileChangedCommand = new DelegateCommand<object>(OnLocalFileChangedCommandAsync);
        //        return _localFileChangedCommand;
        //    }
        //}
        /// <summary>
        /// 保存视图定义
        /// </summary>
        public ICommand saveCurView
        {
            get
            {
                if (_saveCurView != null) return _saveCurView;
                _saveCurView = new DelegateCommand<object>(OnSaveCurView);
                return _saveCurView;
            }
        }
        public ICommand SaveAsExcelCommand
        {
            get
            {
                if (_SaveAsExcelCommand == null)
                {
                    _SaveAsExcelCommand = new DelegateCommand<object>(OnSaveAsExcelCommand);
                }
                return _SaveAsExcelCommand;
            }
        }


        ///// <summary>
        ///// 本地文件存储。
        ///// </summary>
        //public ICommand SaveLocalFileCommand
        //{
        //    get
        //    {
        //        if (_localFileSaveCommand != null) return _localFileSaveCommand;
        //        _localFileSaveCommand = new DelegateCommand<object>(OnLocalFileSaveCommandAsync);
        //        return _localFileSaveCommand;
        //    }
        //}

        ///// <summary>
        ///// 本地文件删除。
        ///// </summary>
        //public ICommand DelLocalFileCommand
        //{
        //    get
        //    {
        //        if (_localFileDelCommand != null) return _localFileDelCommand;
        //        _localFileDelCommand = new DelegateCommand<object>(OnLocalFileDelCommandAsync);
        //        return _localFileDelCommand;
        //    }
        //}

        /// <summary>
        /// 服务器数据存储。
        /// </summary>
        public ICommand ServerDataSaveCommand
        {
            get
            {
                if (_serverDataSaveCommand != null) return _serverDataSaveCommand;
                _serverDataSaveCommand = new DelegateCommand<object>(OnServerDataSaveCommandAsync);
                return _serverDataSaveCommand;
            }
        }
        /// <summary>
        /// 列选择。
        /// </summary>
        public ICommand ColumnSelectCommand
        {
            get
            {
                if (_columnSelectCommand != null) return _columnSelectCommand;
                _columnSelectCommand = new DelegateCommand<object>(OnColumnSelectCommandAsync);
                return _columnSelectCommand;
            }
        }

        public ICommand columnOrderChanged
        {
            get
            {
                if (_columnOrderChanged != null) return _columnOrderChanged;
                _columnOrderChanged = new DelegateCommand<object>(OnColumnOrderChanged);
                return _columnOrderChanged;
            }
        }




        /// <summary>
        /// 本地数据文件列表。
        /// </summary>
        public FileDataInfo SelectedFile
        {
            get { return _selectFile; }
            set { SetProperty(ref _selectFile, value); }
        }

        /// <summary>
        /// 本地数据文件列表。
        /// </summary>
        public ObservableCollection<FileDataInfo> LocalFileList
        {
            get { return _localFileList; }
            set { SetProperty(ref _localFileList, value); }
        }
        #endregion

        #region Init
        protected override void OnInitPage(object obj)
        {
            LoadLocalFileList();
            SelectedFile = LocalFileList[0];
        }
        /// <summary>
        /// 加载本地数据文件
        /// </summary>
        private void LoadLocalFileList()
        {
            LocalFileList.Clear();
            LocalFileList.Add(new FileDataInfo { ExtName = "", FileName = "未选择任何文件", Size = 0 });
            var files = FileHelper.GetFiles(AppDomain.CurrentDomain.BaseDirectory.CombinePath("Data"), "*.IndexTable");
            if (files != null) LocalFileList.AddRange(files);

        }

        /// <summary>
        /// 本文件加载时，加载动态列信息。
        /// </summary>
        protected override void LoadPropertyInfos()
        {
            var columns = GlobalObject.IndexTablePropertyInfos;//这时就已经能反映最新的选择的列了（isvisible==true）。但是为什么呢？没看懂在哪里修改了
            _dynamicPropertyInfos.Clear();
            _dynamicPropertyInfos.AddRange(columns.OrderBy(X => X.Order));//否则就按加的前后顺序来排序了，即OrigDisplayName（因为后端是这样orderby的）
        }

        /// <summary>
        /// <inheritdoc/>
        /// </summary>
        protected override void BackgroundWorkerLoadComplete(RunWorkerCompletedEventArgs e)
        {
            var obj = e.Result as SimpleModel<dynamic, int>;
            if (obj == null)
            {
                return;
            }
            this.TableData = obj.v1;
            if (this.CountRecord != obj.v2)
            {
                this.CountRecord = obj.v2;
            }
        }

        /// <summary>
        /// <inheritdoc/>
        /// </summary>
        protected override async Task<object> ViewModelLoadAsync(object model)
        {
            if (_localLoad)
            {
                return null;// await LoadLocalFile();
            }
            else
            {
                return await LoadServerData();
            }
        }
        /// <summary>
        /// 加载本地文件
        /// </summary>
        /// <returns></returns>
        //private async Task<SimpleModel<dynamic, int>> LoadLocalFile()
        //{
        //    var fileName = _selectFile.FullName;
        //    var obj = new SimpleModel<dynamic, int>();
        //    var jsonStr = FileHelper.ReadFileText(fileName);
        //    obj.v1 = await _dynamicDataApi.LoadIndexTableFromJsonAsync(jsonStr);
        //    var list = obj.v1 as IList;
        //    if (list != null)
        //        obj.v2 = list.Count;
        //    else
        //        obj.v2 = 0;
        //    return obj;
        //}

        /// <summary>
        /// 加载webapi数据
        /// </summary>
        /// <returns></returns>
        private async Task<SimpleModel<dynamic, int>> LoadServerData()
        {
            var obj = new SimpleModel<dynamic, int>
            {
                v1 = new ObservableCollection<object>(),
                v2 = 0
            };
            if (_currentNodes == null)
            {
                return obj;
            }
            string units = _currentNodes.ExpandToString(t => t.Id, ",");
            if (units.IsNullOrEmpty())
            {
                return obj;
            }
            var ColsChecked = _dynamicPropertyInfos.Where(x => x.IsVisible).Select(x => x.PropertyName).ToList();
            var PropsChecked = GlobalObject.EDE_Index_AllColumns.Where(x => ColsChecked.Contains(x.WPF_UniqueName)).ToList();
            var dataStructObj = await _dynamicDataApi.GetIndexTableDynamicsAsync(GlobalObject.CurrentProject.ProjId.ToString(), PropsChecked, units, 0, 0);
            obj.v1 = dataStructObj.Data;
            obj.v2 = dataStructObj.Count;
            return obj;
        }
        #endregion

        #region Command
        /// <summary>
        /// 列选择
        /// </summary>
        private async void OnColumnSelectCommandAsync(object obj)
        {
            var para = new DialogParameters();
            var items = new List<DynamicPropertyInfo>();

            foreach (var item in Columns.OrderBy(x => x.ToolTip.ToString()))//所有的列
            {
                //items.Add(new ContentItemModel(item.Name, item.Header.ToString(), ContentItemType.Text, false)
                //{
                //    IsVisible = item.IsVisible
                //});
                items.Add(new DynamicPropertyInfo()
                {
                    PropertyName = item.UniqueName.ToString(),
                    SPIColName = item.ToolTip.ToString(),//临时当做属性名
                    DisplayName = item.Header.ToString(),
                    IsVisible = item.IsVisible,
                });
            }


            para.Add("Items", items);
            Dialog.ShowDialog("IndexTableColumnSelect", para,
            d =>
            {
                if (d.Result == ButtonResult.OK)
                {
                    items = d.Parameters.GetValue<List<DynamicPropertyInfo>>("Items");
                    foreach (var column in Columns)
                    {
                        var item = items.FirstOrDefault(x => x.PropertyName == column.UniqueName.ToString());//打开dialog的时候就是UniqueName过去的
                        if (item != null)
                        {
                            column.IsVisible = true;
                            column.Header = item.DisplayName;//打开dialog的时候就是Header过去的
                        }
                        else
                        {
                            column.IsVisible = false;
                        }

                    }
                    foreach (var prop in _dynamicPropertyInfos)
                    {
                        var item = items.FirstOrDefault(x => x.PropertyName == prop.PropertyName);
                        if (item != null)
                        {
                            prop.IsVisible = true;
                        }
                        else
                        {
                            prop.IsVisible = false;
                        }
                    }
                }
            });

            await Task.Run(() => { });
        }
        /// <summary>
        /// 保存数据至服务。
        /// </summary>
        /// <param name="obj"></param>
        private async void OnServerDataSaveCommandAsync(object obj)
        {
            var editList = new List<DynamicEntity>();
            var tmpData = (IList)TableData;
            if (TableData == null)
            {
                Dialog.ShowAltert("未修改任何索引表数据，无需执行保存操作!!!");
                return;
            }
            foreach (var item in tmpData)
            {
                var editObj = item as DynamicEntity;
                if (editObj != null && editObj.IsModify)
                {
                    editList.Add(editObj);
                }
            }

            if (editList.Count < 1)
            {
                Dialog.ShowAltert("未修改任何索引表数据，无需执行保存操作!!!");
                return;
            }
            var codeServ = new CodeListService();
            var dic = ObjectHelper.GetObjDic(_dynamicPropertyInfos.Where(X => X.IsVisible == true || X.PrimaryKey == true).ToList(), editList);
            var resultDic = new List<SPIPatchObj>();
            foreach (var dicObj in dic)
            {
                foreach (var item in dicObj.v2)
                {
                    var name = _dynamicPropertyInfos.First(x => x.PropertyName == item.Key);
                    if (name != null)
                    {
                        var values = await codeServ.GetDropDownListByAttrAsync(name.ItemAttributionId); //.GetValueOrNull(GlobalObject.CurrentProject.ProjId.ToString() + "_" + name.ItemAttributionId.ToString());
                        if (values != null)
                        {
                            var id = values.FirstOrDefault(x => x.Name == item.Value)?.Id;
                            if (!string.IsNullOrEmpty(id))
                            {
                                dicObj.v2[item.Key] = id;
                            }
                        }
                    }

                }
                resultDic.Add(new SPIPatchObj { Id = dicObj.v1, keyValuePairs = dicObj.v2 });
            }

            try
            {
                //var columns = await _dynamicDataApi.GetIndexTableDataColumnsAsync(GlobalObject.CurrentProject.ProjId.ToString());//这里是没有意义的。因为要更新的列是根据用户选择的来的，而不是根据服务器里固定的来的。
                var ColsChecked = _dynamicPropertyInfos.Where(x => x.IsVisible).Select(x => x.PropertyName).ToList();
                var columns = GlobalObject.EDE_Index_AllColumns.Where(x => ColsChecked.Contains(x.WPF_UniqueName)).ToList();
                var edeObj = new EDESubmitObj
                {
                    ViewId = "",
                    ItemName = "instrument",
                    columns = columns,
                    Objs = resultDic,
                };
                var b = await _dynamicDataApi.SaveIndexTableAsync(GlobalObject.CurrentProject.ProjId.ToString(), edeObj);
                if (b)
                {
                    foreach (var item in editList)
                    {
                        item.IsModify = false;
                    }
                    //Dialog.ShowMessage("索引表数据保存至远程服务器成功!!!"); 这里不知为啥提示窗口会后置。
                    MessageBox.Show("索引表数据保存至远程服务器成功!!!");
                }
                else
                    Dialog.ShowAltert("索引表数据保存至远程服务器失败!!!");
            }
            catch (Exception x)
            {
                var msg = $"索引表数据保存至远程服务器失败：{x.Message}";
                LoggerHelper.Current.Error(msg, x);
                Dialog.ShowAltert(msg);
            }
        }

        ///// <summary>
        ///// 加载数据来自本地文件。
        ///// </summary>
        ///// <param name="obj"></param>
        //private void OnLocalFileChangedCommandAsync(object obj)
        //{
        //    if (_selectFile != null && _selectFile.Size > 0)
        //    {
        //        _localLoad = true;
        //        this.CountRecord = 0;
        //    }
        //    else
        //    {
        //        _localLoad = false;
        //        this.CountRecord = 0;
        //    }
        //    if (!_isLoding)
        //        this.IsBusy = true;
        //}
        ///// <summary>
        ///// 删除本地文件
        ///// </summary>
        ///// <param name="obj"></param>
        //private void OnLocalFileDelCommandAsync(object obj)
        //{
        //    string fileName = "";
        //    if (_selectFile != null && _selectFile.Size > 0)
        //    {
        //        Dialog.ShowQuestion($"您确认要删除当前选择的本地{_selectFile.FileName}索引表数据吗？", d =>
        //        {
        //            if (d.Result == ButtonResult.Yes)
        //            {
        //                fileName = _selectFile.FullName;
        //            }
        //        });
        //        if (fileName.IsNotEmptyOrNull())
        //        {
        //            try
        //            {
        //                var fileInfo = new FileInfo(fileName);
        //                fileInfo.Delete();
        //                LoadLocalFileList();
        //                SelectedFile = LocalFileList[0];
        //                return;
        //            }
        //            catch (Exception x)
        //            {
        //                var msg = $"{fileName} 文件删除失败：{x.Message}";
        //                LoggerHelper.Current.Error(msg, x);
        //                Dialog.ShowAltert(msg);
        //                return;
        //            }
        //        }
        //    }
        //    else
        //    {
        //        Dialog.ShowAltert("未选择任何需要删除的本地文件！！！");
        //        return;
        //    }
        //}

        ///// <summary>
        ///// 保存数据至本地文件。
        ///// </summary>
        ///// <param name="obj"></param>
        //private void OnLocalFileSaveCommandAsync(object obj)
        //{
        //    string fileName = "";
        //    var currentSelect = "";
        //    if (_selectFile != null && _selectFile.Size > 0)
        //    {
        //        Dialog.ShowQuestion("您确认要覆盖当前选择的本地索引表数据吗？", d =>
        //        {
        //            if (d.Result == ButtonResult.Yes)
        //            {
        //                fileName = _selectFile.FullName;
        //                currentSelect = _selectFile.FileName;
        //            }
        //        });
        //    }
        //    else
        //    {
        //        fileName = AppDomain.CurrentDomain.BaseDirectory.CombinePath($"Data\\{DateTime.Now.ToString("yyyy-MM-dd-HH-mm-ss")}.IndexTable");
        //    }
        //    if (fileName.IsNullOrEmpty())
        //        return;

        //    var result = JsonConvert.SerializeObject(this.TableData);
        //    try
        //    {
        //        bool wR = FileHelper.WriteFileText(fileName, result);
        //        if (wR)
        //        {
        //            _localLoad = true;
        //            _isLoding = true;
        //            LoadLocalFileList();
        //            if (currentSelect.IsNotEmptyOrNull())
        //            {
        //                var sel = this.LocalFileList.First(f => f.FileName == currentSelect);
        //                if (sel != null)
        //                {
        //                    SelectedFile = sel;
        //                }
        //            }
        //            else
        //            {
        //                SelectedFile = LocalFileList[0];
        //            }
        //            Dialog.ShowMessage("本地文件保存成功！！！");
        //            _isLoding = false;
        //        }
        //        else
        //        {
        //            Dialog.ShowAltert("本地文件保存失败!!!");
        //            return;
        //        }
        //    }
        //    catch (Exception x)
        //    {
        //        var msg = $"本地文件保存失败：{x.Message}";
        //        LoggerHelper.Current.Error(msg, x);
        //        Dialog.ShowAltert(msg);
        //    }

        //}

        private void OnColumnOrderChanged(object obj)
        {
            //var type = obj.GetType();
            //var objEvent = obj as GridViewColumnEventArgs;
            //var col = objEvent.Column;
            //var index = col.DisplayIndex;
            //var name = col.UniqueName;
            //var tag = col.Tag as SimpleModel<string, decimal>;

            //var test = Columns.First(x => x.Header.ToString() == "仪表用途");
            //if (test != null)
            //{
            //    var index2 = test.DisplayIndex;
            //}
            //var test2 = _dynamicPropertyInfos.First(x => x.DisplayName == "仪表用途");
            //if (test2 != null)
            //{
            //    var index3 = test2.Order;
            //}
            //Console.WriteLine("");
        }


        /// <summary>
        /// 保存视图
        /// </summary>
        /// <param name="obj"></param>
        /// <exception cref="NotImplementedException"></exception>
        private void OnSaveCurView(object obj)
        {
            List<string> info = new List<string>();
            //"IndexTable"
            var selectCols = Columns.Where(X => X.IsVisible).OrderBy(x => x.DisplayIndex).ToList();
            //把Columns里的DisplayIndex 和 DisplayName -》 原始 attr里的 SeqNum 和 IsDisplay
            for (int i = 0; i < selectCols.Count(); i++)
            {
                var dynamicProperty = GlobalObject.IndexTablePropertyInfos.FirstOrDefault(x => x.PropertyName == selectCols[i].UniqueName.ToString());
                if (dynamicProperty != null)
                {
                    dynamicProperty.DisplayName = selectCols[i].Header.ToString();
                    dynamicProperty.Order = i + 1;
                    info.Add(dynamicProperty.PropertyName + "@" + selectCols[i].Header.ToString());
                }

            }
            //_dynamicPropertyInfos 不能用这个，这个会在新打开indexTable时被初始化 LoadPropertyInfos函数里
            var noSelectCols = GlobalObject.IndexTablePropertyInfos.Where(x => !selectCols.Select(c => c.UniqueName.ToString()).Contains(x.PropertyName));
            foreach (var prop in noSelectCols)
            {
                prop.Order = 0;
            }

            //写入ini文件
            var config = ConfigHelper.ReadConfig();
            config.IndexViewColDef.Clear();
            config.IndexViewColDef.Add(string.Join("|", info));

            ConfigHelper.WriteConfig(config);
            Dialog.ShowMessage("视图保存成功!!!");

        }

        /// <summary>
        /// 另存为excel
        /// </summary>
        /// <param name="obj"></param>
        /// <exception cref="NotImplementedException"></exception>
        private void OnSaveAsExcelCommand(object obj)
        {
            string fileName = "";

            fileName = Path.Combine(System.Environment.GetFolderPath(System.Environment.SpecialFolder.MyDocuments), "索引表视图导出" + ".xlsx");

            //string result = JsonConvert.SerializeObject(this.TableData);
            try
            {
                var ColsChecked = _dynamicPropertyInfos.Where(x => x.IsVisible).Select(x => x.PropertyName).ToList();
                var ColsDisplayChecked = _dynamicPropertyInfos.Where(x => x.IsVisible).Select(x => x.DisplayName).ToList();
                // 创建Excel文件  
                IWorkbook workbook = new XSSFWorkbook(); // 使用.xlsx格式  
                ISheet sheet = workbook.CreateSheet("索引表视图导出");


                ICellStyle cellStyle = workbook.CreateCellStyle();
                IFont font = workbook.CreateFont();
                font.IsBold = true; // 设置字体加粗  
                font.FontHeightInPoints = 14; // 设置字体大小  
                cellStyle.SetFont(font); // 将字体设置到单元格样式中

                cellStyle.FillForegroundColor = IndexedColors.Yellow.Index; // 设置背景颜色为黄色  
                cellStyle.FillPattern = FillPattern.SolidForeground; // 设置填充模式为纯色填充

                cellStyle.BorderTop = BorderStyle.Thin; // 设置上边框为细线  
                cellStyle.BorderBottom = BorderStyle.Thin; // 设置下边框为细线  
                cellStyle.BorderLeft = BorderStyle.Thin; // 设置左边框为细线  
                cellStyle.BorderRight = BorderStyle.Thin; // 设置右边框为细线

                // 创建表头  
                IRow headerRow = sheet.CreateRow(0);
                int colIndex = 0;
                foreach (var col in ColsDisplayChecked)
                {
                    var cell = headerRow.CreateCell(colIndex);
                    cell.CellStyle = cellStyle; // 将样式应用到单元格上
                    cell.SetCellValue(col);
                    sheet.SetColumnWidth(colIndex, ExcelHelper.CalculateColumnWidth(cell));
                    colIndex++;
                }
                // 创建其他表头单元格...  

                // 批量写入数据  
                int rowIndex = 1; // 从第二行开始写入数据，因为第一行是表头  
                foreach (var datarow in TableData)
                {
                    IRow row = sheet.CreateRow(rowIndex++);
                    colIndex = 0;
                    // 写入其他属性到对应的单元格...  
                    foreach (var col in ColsChecked)
                    {
                        object piValue = Reflect.GetPropValue(datarow, col);
                        row.CreateCell(colIndex).SetCellValue(piValue == null ? "" : piValue.ToString());
                        colIndex++;
                    }
                    row = null;
                }

                // 保存Excel文件到磁盘  
                using (FileStream file = new FileStream(fileName, FileMode.Create, FileAccess.Write))
                {
                    workbook.Write(file);
                }
                workbook.Close();

                //var x = ObjectHelper.GetObjDic(ColsChecked2, TableData);
                bool wR = true;// FileHelper.WriteFileText(fileName, result);
                if (wR)
                {
                    _isLoding = true;

                    Dialog.ShowMessage("本地文件保存成功！！！稍后会打开所在文件夹。");
                    //Process.Start("explorer.exe", System.Environment.GetFolderPath(System.Environment.SpecialFolder.MyDocuments));//打开文件夹
                    ExplorerFileExtensions.ExplorerFile(fileName);
                    _isLoding = false;
                }
                else
                {
                    Dialog.ShowAltert("本地文件保存失败!!!");
                    return;
                }
            }
            catch (Exception x)
            {
                var msg = $"本地文件保存失败：{x.Message}";
                LoggerHelper.Current.Error(msg, x);
                Dialog.ShowAltert(msg);
            }
        }
        #endregion
    }
}
